package com.lh.runmanage.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lh.runmanage.dto.Children;
import com.lh.runmanage.dto.MenuChildren;
import com.lh.runmanage.dto.ProjectDto;
import com.lh.runmanage.model.*;
import com.lh.runmanage.model.InPutParam.*;
import com.lh.runmanage.myenum.ResultCode;
import com.lh.runmanage.service.*;
import com.lh.runmanage.unit.GetPropertiesClass;
import com.lh.runmanage.unit.LhClass;
import com.lh.runmanage.unit.RedisOperator;
import com.lh.runmanage.unit.ResultStruct;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ：梁昊，后端工程师：梁昊
 * @create 2021-07-12 14:43
 * @function
 * @editLog
 */
@RestController
@RequestMapping("/projectController")
@Api(value = "项目控制层", description = "系统运行态势平台管理端相关方法")
public class ProjectController {
    @Autowired
    ProjectService projectService;
    @Autowired
    GetPropertiesClass getPropertiesClass;
    @Autowired
    LogService logService;
    @Autowired
    UserService userService;
    @Autowired
    RedisOperator redisOperator;
    @Autowired
    ColService colService;
    @Autowired
    ProjAvgService projAvgService;
    @Autowired
    ProjectAndProductService projectAndProductService;
    @Autowired
    MenuAuthorityService menuAuthorityService;

    private int insertLog(@RequestParam(value = "userId") String userId
            , @RequestParam(value = "content", required = false) String content) {
        LogInParam logInParam = new LogInParam();
        logInParam.setUserId(userId);
        logInParam.setUserName(userService.selectUserNameById(userId));
        logInParam.setContent(content);
        return logService.insertLog(logInParam);
    }

    /**
     * 查询Token---管理端表格，方法ID：SE20210712135608806C8DE825CD258
     *
     * @param projName 表vou_project,字段名projName:项目名称
     * @return 返回项目全信息
     */
    @ApiOperation(value = "查询Token---管理端表格[返回项目全信息],方法ID：SE20210712135608806C8DE825CD258", notes = "/projectController/V1/selectProjectByPageGrid?projName=projName")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projName", value = "项目名称", dataType = "String")
            , @ApiImplicitParam(name = "page", value = "当前页数", dataType = "String")
            , @ApiImplicitParam(name = "limit", value = "每页条数", dataType = "String")
    })
    @PostMapping("/V1/selectProjectByPageGrid")
    public ResultVOPage selectProjectByPageGrid(@RequestParam(value = "projName", required = false) String projName
            , @RequestParam(value = "page", defaultValue = "1") int page
            , @RequestParam(value = "limit", defaultValue = "10") int limit) throws UnsupportedEncodingException {
        if (projName != null) {
            projName = projName.trim();
            if (projName.getBytes("gbk").length > 30) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：30", "projName"), ResultVOPage.class, null);
            }
        }

        PageHelper.startPage(page, limit);
        final List<ProjectModel> projectModels = projectService.selectProjectByPageGrid(projName);
        PageInfo pageInfo = new PageInfo<>(projectModels, limit);
        return ResultStruct.successPage(projectModels, pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal());
    }

    /**
     * 展示端：D3，分页得到前20项目坐标列表，方法ID：SE20210712140157106ED78797BDD24
     *
     * @return 返回前20项目坐标列表
     */
    @ApiOperation(value = "展示端方法：D3，分页得到前20项目坐标列表[返回前20项目坐标列表],方法ID：SE20210712140157106ED78797BDD24", notes = "/projectController/V1/selectProjectSite?")
    @PostMapping("/V1/selectProjectSiteD3")
    public ResultVO selectProjectSiteD3() {
        final List<String> idOrderBy = get20IdOrderBy();
        if (idOrderBy != null) {
            List<ProjectSiteModel> projectSiteModels = projectService.selectProjectSite(idOrderBy);
            return ResultStruct.success(projectSiteModels);
        } else
            return ResultStruct.success(null);
    }


    /**
     * 加个新项目，方法ID：IN2021071214100523445CF7B810F9A
     *
     * @param proCode        项目Code（不可重复）
     * @param projName       项目名称
     * @param contSignDate   合同签订日期
     * @param projDoDate     实施开始日期
     * @param projOnlineDate 预计上线日期
     * @param totalType      统计周期
     * @param remark         备注
     * @return 影响条件
     */
    @ApiOperation(value = "加个新项目[影响条件],方法ID：IN2021071214100523445CF7B810F9A", notes = "/projectController/V1/insertProjectAll?id=id&proCode=proCode&projName=projName&contSignDate=contSignDate&projDoDate=projDoDate&projOnlineDate=projOnlineDate&projOverDate=projOverDate&projOverSign=projOverSign&token=token&xPoint=xPoint&yPoint=yPoint&totalType=totalType&remark=remark")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "proCode", value = "项目Code（不可重复）, 长度：100", dataType = "String", required = true)
            , @ApiImplicitParam(name = "projName", value = "项目名称, 长度：30", dataType = "String", required = true)
            , @ApiImplicitParam(name = "contSignDate", value = "合同签订日期, 长度：0", dataType = "Date", required = true)
            , @ApiImplicitParam(name = "projDoDate", value = "实施开始日期, 长度：0", dataType = "Date", required = true)
            , @ApiImplicitParam(name = "projOnlineDate", value = "预计上线日期, 长度：0", dataType = "Date", required = true)
            , @ApiImplicitParam(name = "xPoint", value = "公鸡地图X坐标, 长度：20", dataType = "String", required = true)
            , @ApiImplicitParam(name = "yPoint", value = "公鸡地图Y坐标, 长度：20", dataType = "String", required = true)
            , @ApiImplicitParam(name = "totalType", value = "统计周期, 长度：4", dataType = "String", required = true)
            , @ApiImplicitParam(name = "remark", value = "备注, 长度：2000", dataType = "String")
    })
    @PostMapping("/V1/insertProjectAll")
    public ResultVO insertProjectAll(@RequestParam(value = "proCode") String proCode
            , @RequestParam(value = "projName") String projName
            , @RequestParam(value = "contSignDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date contSignDate
            , @RequestParam(value = "projDoDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date projDoDate
            , @RequestParam(value = "projOnlineDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date projOnlineDate
            , @RequestParam(value = "xPoint", defaultValue = "0.000000000000000") BigDecimal xPoint
            , @RequestParam(value = "yPoint", defaultValue = "0.000000000000000") BigDecimal yPoint
            , @RequestParam(value = "totalType", defaultValue = "月") String totalType
            , @RequestParam(value = "remark", required = false) String remark) throws UnsupportedEncodingException {

        if (proCode != null) {
            proCode = proCode.trim();
            if (proCode.getBytes("gbk").length > 100) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：100", "proCode"), ResultVO.class, null);
            }
        }
        if (projName != null) {
            projName = projName.trim();
            if (projName.getBytes("gbk").length > 30) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：30", "projName"), ResultVO.class, null);
            }
        }
        if (totalType != null) {
            totalType = totalType.trim();
            if (totalType.getBytes("gbk").length > 4) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：4", "totalType"), ResultVO.class, null);
            }
        }
        if (remark != null) {
            remark = remark.trim();
            if (remark.getBytes("gbk").length > 2000) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：2000", "remark"), ResultVO.class, null);
            }
        }

        if (projDoDate.compareTo(contSignDate) < 0) {
            return ResultStruct.error("实施开始日期不能晚于合同签订日期", ResultVO.class, int.class);
        }
        if (projOnlineDate.compareTo(projDoDate) < 0) {
            return ResultStruct.error("预计上线日期不能晚于实施开始日期", ResultVO.class, int.class);
        }
        ProjectInParam projectInParam = new ProjectInParam();
        String mainKey = LhClass.getPicturyKey(Short.valueOf(getPropertiesClass.getPort()));//这里引用架包中的生成主键方法
        projectInParam.setId(mainKey);
        projectInParam.setProCode(proCode);
        projectInParam.setProjName(projName);
        projectInParam.setContSignDate(contSignDate);
        projectInParam.setProjDoDate(projDoDate);
        projectInParam.setProjOnlineDate(projOnlineDate);
        projectInParam.setProjOverSign(false);
        projectInParam.setProjOverDate(projOnlineDate);

        final String projectToken = redisOperator.writeProjectToken(mainKey);
        projectInParam.setToken(projectToken);
        projectInParam.setRemark(remark);
        projectInParam.setXPoint(xPoint);
        projectInParam.setYPoint(yPoint);
        projectInParam.setTotalType(totalType);
        projectInParam.setRemark(remark);
        int resultCount = projectService.insertProjectAll(projectInParam);
        if (resultCount > 0)
            return ResultStruct.success(resultCount);
        else if (resultCount == -1000)
            return ResultStruct.error("重复，不允许增加", ResultVO.class, int.class);
        else
            return ResultStruct.error("增加失败", ResultVO.class, int.class);
    }

    /**
     * 修改项目基础信息，方法ID：UP2021071214100671052695DD8D8E2
     *
     * @param id             主键
     * @param proCode        项目Code（不可重复）
     * @param projName       项目名称
     * @param contSignDate   合同签订日期
     * @param projDoDate     实施开始日期
     * @param projOnlineDate 预计上线日期
     * @param projOverDate   实际上线日期
     * @param projOverSign   是否完成（0：未完成上线、1：完成上线）
     * @param totalType      统计周期
     * @param remark         备注
     * @return 影响条件
     */
    @ApiOperation(value = "修改项目基础信息[影响条件],方法ID：UP2021071214100671052695DD8D8E2", notes = "/projectController/V1/updateProjectById?id=id&proCode=proCode&projName=projName&contSignDate=contSignDate&projDoDate=projDoDate&projOnlineDate=projOnlineDate&projOverDate=projOverDate&projOverSign=projOverSign&totalType=totalType&remark=remark")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键, 长度：50", dataType = "String", required = true)
            , @ApiImplicitParam(name = "proCode", value = "项目Code（不可重复）, 长度：100", dataType = "String")
            , @ApiImplicitParam(name = "projName", value = "项目名称, 长度：30", dataType = "String")
            , @ApiImplicitParam(name = "contSignDate", value = "合同签订日期, 长度：0", dataType = "Date")
            , @ApiImplicitParam(name = "projDoDate", value = "实施开始日期, 长度：0", dataType = "Date")
            , @ApiImplicitParam(name = "projOnlineDate", value = "预计上线日期, 长度：0", dataType = "Date")
            , @ApiImplicitParam(name = "projOverDate", value = "实际上线日期, 长度：0", dataType = "Date")
            , @ApiImplicitParam(name = "projOverSign", value = "是否完成（0：未完成上线、1：完成上线）, 长度：1", dataType = "Boolean")
            , @ApiImplicitParam(name = "totalType", value = "统计周期, 长度：4", dataType = "String")
            , @ApiImplicitParam(name = "remark", value = "备注, 长度：2000", dataType = "String")
    })
    @PostMapping("/V1/updateProjectById")
    public ResultVO updateProjectById(@RequestParam(value = "id") String id
            , @RequestParam(value = "proCode", required = false) String proCode
            , @RequestParam(value = "projName", required = false) String projName
            , @RequestParam(value = "contSignDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date contSignDate
            , @RequestParam(value = "projDoDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date projDoDate
            , @RequestParam(value = "projOnlineDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date projOnlineDate
            , @RequestParam(value = "projOverDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date projOverDate
            , @RequestParam(value = "projOverSign", required = false) boolean projOverSign
            , @RequestParam(value = "totalType", required = false) String totalType
            , @RequestParam(value = "remark", required = false) String remark) throws UnsupportedEncodingException {
        if (id != null) {
            id = id.trim();
            if (id.getBytes("gbk").length > 50) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：50", "id"), ResultVO.class, null);
            }
        }
        if (proCode != null) {
            proCode = proCode.trim();
            if (proCode.getBytes("gbk").length > 100) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：100", "proCode"), ResultVO.class, null);
            }
        }
        if (projName != null) {
            projName = projName.trim();
            if (projName.getBytes("gbk").length > 30) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：30", "projName"), ResultVO.class, null);
            }
        }
        if (totalType != null) {
            totalType = totalType.trim();
            if (totalType.getBytes("gbk").length > 4) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：4", "totalType"), ResultVO.class, null);
            }
        }
        if (remark != null) {
            remark = remark.trim();
            if (remark.getBytes("gbk").length > 2000) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：2000", "remark"), ResultVO.class, null);
            }
        }

        ProjectInParam projectInParam = new ProjectInParam();
        projectInParam.setId(id);
        projectInParam.setProCode(proCode);
        projectInParam.setProjName(projName);
        projectInParam.setContSignDate(contSignDate);
        projectInParam.setProjDoDate(projDoDate);
        projectInParam.setProjOnlineDate(projOnlineDate);
        projectInParam.setProjOverDate(projOverDate);
        projectInParam.setProjOverSign(projOverSign);
        projectInParam.setTotalType(totalType);
        projectInParam.setRemark(remark);
        int resultCount = projectService.updateProjectById(projectInParam);
        if (resultCount > 0)
            return ResultStruct.success(resultCount);
        else if (resultCount == -1000)
            return ResultStruct.error("重复，不允许修改", ResultVO.class, int.class);
        else
            return ResultStruct.error("修改失败", ResultVO.class, int.class);
    }

    /**
     * 删除项目及其它相关信息，方法ID：DE20210712141007914E4990A7B4CFB
     *
     * @param id 主键
     * @return 影响条件
     */
    @ApiOperation(value = "删除项目及其它相关信息[影响条件],方法ID：DE20210712141007914E4990A7B4CFB", notes = "/projectController/V1/deleteProjectById?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", dataType = "String")
    })
    @PostMapping("/V1/deleteProjectById")
    public ResultVO deleteProjectById(@RequestParam(value = "id", required = false) String id) {
        id = id == null ? id : id.trim();

        ProjectInParam projectInParam = new ProjectInParam();
        projectInParam.setId(id);
        final ProjectTokenModel projectTokenModel = projectService.selectProjectTokenById(id);
        int updateCount = projectService.deleteProjectById(projectInParam);
        if (updateCount > 0) {
            if (projectTokenModel != null) {
                final String token = projectTokenModel.getToken();
                if (token != null) {
                    redisOperator.deleteProjectToken(token);
                }
            }
            return ResultStruct.success(updateCount);
        } else
            return ResultStruct.error("删除失败", ResultVO.class, int.class);
    }

    public <S> S fieldError(String fieldName, String fieldTitle, int length, Class<S> sClass) throws UnsupportedEncodingException {
        if (fieldName != null) {
            fieldName = fieldName.trim();
            if (fieldName.getBytes("gbk").length > length) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：%d"
                        , fieldTitle
                        , length), sClass, null);
            } else
                return null;
        } else
            return null;
    }

    /**
     * 修改项目Token，方法ID：UP202107121450231045AF9ACBC8425
     *
     * @param id    主键
     * @param token 项目TOKEN（不可重复）
     * @return 影响条件
     */
    @ApiOperation(value = "修改项目Token[影响条件],方法ID：UP202107121450231045AF9ACBC8425", notes = "/projectController/V1/updateProjectTokenById?id=id&token=token")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键, 长度：50", dataType = "String", required = true)
            , @ApiImplicitParam(name = "token", value = "项目TOKEN（不可重复）, 长度：32", dataType = "String", required = true)
    })
    @PostMapping("/V1/updateProjectTokenById")
    public ResultVO updateProjectTokenById(@RequestParam(value = "id") String id
            , @RequestParam(value = "token") String token) throws UnsupportedEncodingException {
        ResultVO resultVO = fieldError(id, "id", 50, ResultVO.class);
        if (resultVO == null || resultVO.getState() != ResultCode.SUCCESS.getCode()) {
            return resultVO;
        }
        resultVO = fieldError(token, "token", 32, ResultVO.class);
        if (resultVO == null || resultVO.getState() != ResultCode.SUCCESS.getCode()) {
            return resultVO;
        }

        ProjectInParam projectInParam = new ProjectInParam();
        projectInParam.setId(id);
        projectInParam.setToken(token);
        int resultCount = projectService.updateProjectTokenById(projectInParam);
        if (resultCount > 0)
            return ResultStruct.success(resultCount);
        else if (resultCount == -1000)
            return ResultStruct.error("重复，不允许修改", ResultVO.class, int.class);
        else
            return ResultStruct.error("修改失败", ResultVO.class, int.class);
    }

    /**
     * 修改项目坐标，方法ID：UP20210712145034727000356B01BFE
     *
     * @param id     主键
     * @param xPoint 公鸡地图X坐标
     * @param yPoint 公鸡地图Y坐标
     * @return 影响条件
     */
    @ApiOperation(value = "修改项目坐标[影响条件],方法ID：UP20210712145034727000356B01BFE", notes = "/projectController/V1/updateProjectSiteById?id=id&xPoint=xPoint&yPoint=yPoint")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键, 长度：50", dataType = "String", required = true)
            , @ApiImplicitParam(name = "xPoint", value = "公鸡地图X坐标, 长度：10", dataType = "String")
            , @ApiImplicitParam(name = "yPoint", value = "公鸡地图Y坐标, 长度：10", dataType = "String")
    })
    @PostMapping("/V1/updateProjectSiteById")
    public ResultVO updateProjectSiteById(@RequestParam(value = "id") String id
            , @RequestParam(value = "xPoint", required = false, defaultValue = " - 128") BigDecimal xPoint
            , @RequestParam(value = "yPoint", required = false, defaultValue = " - 128") BigDecimal yPoint) throws UnsupportedEncodingException {
        if (id != null) {
            id = id.trim();
            if (id.getBytes("gbk").length > 50) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：50", "id"), ResultVO.class, null);
            }
        }
        if (xPoint.compareTo(BigDecimal.valueOf(-128)) == 0 || yPoint.compareTo(BigDecimal.valueOf(-128)) == 0) {
            return ResultStruct.error("请输入合法坐标值", ResultVO.class, null);
        }
        ProjectInParam projectInParam = new ProjectInParam();
        projectInParam.setId(id);
        projectInParam.setXPoint(xPoint);
        projectInParam.setYPoint(yPoint);
        int resultCount = projectService.updateProjectSiteById(projectInParam);
        if (resultCount > 0)
            return ResultStruct.success(resultCount);
        else
            return ResultStruct.error("修改失败", ResultVO.class, int.class);
    }

    /**
     * 修改项目统计类型，方法ID：UP20210712155406696B797B4D62ADC
     *
     * @param id        主键
     * @param totalType 统计周期
     * @return 影响条件
     */
    @ApiOperation(value = "修改项目统计类型[影响条件],方法ID：UP20210712155406696B797B4D62ADC", notes = "/projectController/V1/updateProjectTotalTypeById?id=id&totalType=totalType")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键, 长度：50", dataType = "String", required = true)
            , @ApiImplicitParam(name = "totalType", value = "统计周期, 长度：4", dataType = "String")
    })
    @PostMapping("/V1/updateProjectTotalTypeById")
    public ResultVO updateProjectTotalTypeById(@RequestParam(value = "id") String id
            , @RequestParam(value = "totalType", required = false) String totalType) throws UnsupportedEncodingException {
        if (id != null) {
            id = id.trim();
            if (id.getBytes("gbk").length > 50) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：50", "id"), ResultVO.class, null);
            }
        }
        if (totalType != null) {
            totalType = totalType.trim();
            if (totalType.getBytes("gbk").length > 4) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：4", "totalType"), ResultVO.class, null);
            }
        }

        ProjectInParam projectInParam = new ProjectInParam();
        projectInParam.setId(id);
        projectInParam.setTotalType(totalType);
        int resultCount = projectService.updateProjectTotalTypeById(projectInParam);
        if (resultCount > 0)
            return ResultStruct.success(resultCount);
        else
            return ResultStruct.error("修改失败", ResultVO.class, int.class);
    }

    /**
     * 展示端方法 ：D5 得到项目、产品、菜单关系树状数据，方法ID：SE202107121722225213EB5CE5A3A89
     *
     * @return 树
     */
    @ApiOperation(value = "展示端方法 ：D5,得到项目、产品、菜单关系树状数据[树],方法ID：SE202107121722225213EB5CE5A3A89", notes = "/projectController/V1/selectProjectTreeByProjectId?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "createDate", value = "数据产生时间", dataType = "Date")
    })
    @PostMapping("/V1/selectProjectTreeByProjectIdListD5")
    public ResultVO selectProjectTreeByProjectIdListD5(@RequestParam(value = "createDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date createDate) {
        final List<String> idOrderBy = get20IdOrderBy();
        if (idOrderBy == null) {
            return ResultStruct.success(null);
        }
        return getProjectTree(idOrderBy, true, createDate);
    }

    /**
     * 展示端方法 ：J2 得到项目、产品、菜单关系树状数据，方法ID：SE202107121722225213EB5CE5A3A99
     *
     * @return 树
     */
    @ApiOperation(value = "展示端方法 ：J2,得到项目、产品、菜单关系树状数据[树],方法ID：SE202107121722225213EB5CE5A3A99", notes = "/projectController/V1/selectProjectTreeByProjectIdListJ2?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", dataType = "String", required = true)
            , @ApiImplicitParam(name = "createDate", value = "数据产生时间", dataType = "Date")
    })
    @PostMapping("/V1/selectProjectTreeByProjectIdListJ2")
    public ResultVO selectProjectTreeByProjectIdListJ2(@RequestParam(value = "projectId") String projectId
            , @RequestParam(value = "createDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date createDate) {
        final List<String> idOrderBy = get20IdOrderBy();
        if (idOrderBy == null) {
            return ResultStruct.success(null);
        }
        return getProjectTree(idOrderBy, true, createDate);
    }

    private ResultVO getProjectTree(List<String> projectLists, boolean filterSign, Date createDate) {
        if (createDate == null) {
            createDate = LhClass.getSameCurrentDate(new Date(), -1);
        } else {
            createDate = LhClass.getSameCurrentDate(createDate, -1);
        }
        MenuFilterModel menuFilterModel = new MenuFilterModel();
        if (!projectLists.isEmpty())
            menuFilterModel.setId(projectLists);
        if (filterSign)
            menuFilterModel.setFilterSign("filter");
        menuFilterModel.setCreateTime(createDate);

        final List<ProjectDto> projectDtos = projectService.selectProjectTreeByProjectIdList(menuFilterModel);
        if (!projectDtos.isEmpty()) {
            if (filterSign) {
                for (ProjectDto projectDto : projectDtos
                ) {
                    final List<Children> getChildren = projectDto.getchildren();
                    for (Children children :
                            getChildren) {
                        List<MenuChildren> childrenList = children.getChildren();
                        for (MenuChildren menuChildren :
                                childrenList) {
                            WeightNumInParam weightNumInParam = new WeightNumInParam();
                            weightNumInParam.setProjectCode(projectDto.getMainId());
                            weightNumInParam.setProductCode(children.getCode());
                            weightNumInParam.setMenuCode(menuChildren.getCode());
                            weightNumInParam.setCreateTime(createDate);
                            final WeigthBaseModel weigthBaseModel = menuAuthorityService.getWeigthNum(weightNumInParam);
                            if (weigthBaseModel != null) {
                                menuChildren.setTitle(String.format("%s(使用次数%d,权数%.2f)"
                                        , menuChildren.getTitle()
                                        , weigthBaseModel.getSumCounter()
                                        , weigthBaseModel.getWeightNum()));
                                menuChildren.setWeigthNum(weigthBaseModel.getWeightNum());
                            }
                            else
                                menuChildren.setWeigthNum(BigDecimal.valueOf(0));
                        }
                        childrenList.stream().sorted(
                                Comparator.comparing(MenuChildren::getWeigthNum).reversed())
                                .collect(Collectors.toList());
//                      children.setChildren(childrenList);
                    }
                }
            }
            return ResultStruct.success(projectDtos);
        } else
            return ResultStruct.success(null);
    }

    /**
     * 得到项目、产品、菜单关系树状数据，方法ID：SE202107121722225213EB5CE5A3A88
     *
     * @param projectId 表vou_project,原字段名id,现字段名mainId:主键
     * @return 树
     */
    @ApiOperation(value = "J7，得到项目、产品、菜单关系树状数据[树],方法ID：SE202107121722225213EB5CE5A3A88", notes = "/projectController/V1/selectProjectTreeByProjectId?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", dataType = "String")
            , @ApiImplicitParam(name = "createDate", value = "数据产生时间", dataType = "Date")


    })
    @PostMapping("/V1/selectProjectTreeByProjectIdJ7")
    public ResultVO selectProjectTreeByProjectIdJ7(@RequestParam(value = "projectId", required = false) String projectId
            , @RequestParam(value = "createDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date createDate) {
        return selectProjectTreeByProjectIdPrivate(projectId, true, createDate);
    }

    /**
     * 得到项目、产品、菜单关系树状数据，方法ID：SE202107121722225213EB5CE5A3A887
     *
     * @param projectId 表vou_project,原字段名id,现字段名mainId:主键
     * @return 树
     */
    @ApiOperation(value = "管理端方法：J77，得到项目、产品、菜单关系树状数据[树],方法ID：SE202107121722225213EB5CE5A3A887", notes = "/projectController/V1/selectProjectTreeByProjectId?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "项目ID", dataType = "String")
    })
    @PostMapping("/V1/selectProjectTreeByProjectIdJ77")
    public ResultVO selectProjectTreeByProjectIdJ77(@RequestParam(value = "projectId", required = false) String projectId) {
        return selectProjectTreeByProjectIdPrivate(projectId, false, null);
    }

    private ResultVO selectProjectTreeByProjectIdPrivate(String projectId, boolean filterSign, Date createTime) {
        List<String> projectList = new ArrayList<>(1);
        if (projectId != null) {
            projectList.add(projectId);
        }
        return getProjectTree(projectList, filterSign, createTime);
    }

    /**
     * 大屏、态势分析页面D1方法，方法ID：D1
     */
    @ApiOperation(value = "展示端方法：大屏、态势分析页面D1方法,方法ID：D1", notes = "/projectController/V1/selectD1")
    @PostMapping("/V1/selectD1")
    public ResultVO selectProjectTotalByCreateDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -1);
        TotalProjectModel totalProjectModel = projectService.selectReportProjectTotal();
        if (totalProjectModel == null) {
            totalProjectModel = new TotalProjectModel();
        }
        int withMonths = getPropertiesClass.getWithMonths();
        calendar.add(Calendar.MONTH, -1 * withMonths);
        TotalProjectModel totalProjectModelOld = projectService.selectProjectTotalByCreateDate(calendar.getTime());
        if (totalProjectModelOld != null) {
            totalProjectModel.setAlreadyExeCounterOld(totalProjectModel.getAlreadyExeCounter() - totalProjectModelOld.getAlreadyExeCounter());
            totalProjectModel.setFinishCounterOld(totalProjectModel.getFinishCounter() - totalProjectModelOld.getFinishCounter());
            totalProjectModel.setNoExeCounterOld(totalProjectModel.getNoExeCounter() - totalProjectModelOld.getNoExeCounter());
            totalProjectModel.setTotalCounterOld(totalProjectModel.getTotalCounter() - totalProjectModelOld.getTotalCounter());
        }
        calendar.clear();
        return ResultStruct.success(totalProjectModel);
    }

    /**
     * 大屏、态势分析页面D1方法，方法ID：D1
     */
    @ApiOperation(value = "展示端方法：大屏页面D2方法,方法ID：D2", notes = "/projectController/V1/selectD2")
    @PostMapping("/V1/selectD2")
    public ResultVO selectD2() {
        return ResultStruct.success(projectService.selectD2());
    }

    /**
     * 展示端：根据项目ID，得到项目基础信息，方法ID：SE202107141816265750AB00AA84D35
     *
     * @param id 表vou_project,字段名id:主键
     * @return 项目基础信息
     */
    @ApiOperation(value = "展示端：根据项目ID，得到项目基础信息[项目基础信息],方法ID：SE202107141816265750AB00AA84D35", notes = "/projectController/V1/selectProjectBaseById?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", dataType = "String", required = true)
    })
    @PostMapping("/V1/selectProjectBaseById")
    public ResultVO selectProjectBaseById(@RequestParam(value = "id") String id) throws UnsupportedEncodingException {
        if (id != null) {
            id = id.trim();
            if (id.getBytes("gbk").length > 50) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：50", "id"), ResultVO.class, null);
            }
        }
        return ResultStruct.success(projectService.selectProjectBaseById(id));
    }

    /**
     * 展示端：根据项目ID，得到项目基础信息，方法ID：SE202107141816265750AB00AA84D35
     *
     * @param id 表vou_project,字段名id:主键
     * @return 项目基础信息
     */
    @ApiOperation(value = "展示端：T1，根据项目ID，得到项目基础信息与平均加权值[项目基础信息],方法ID：SE202107141816265750AB00AA84D36", notes = "/projectController/V1/selectProjectBaseById?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "项目ID", dataType = "String", required = true)
            , @ApiImplicitParam(name = "createDate", value = "数据生成日期", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectT1")
    public ResultVO selectProjectAndParaById(@RequestParam(value = "id") String id
            , @RequestParam(value = "createDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date createDate) throws UnsupportedEncodingException {
        if (id != null) {
            id = id.trim();
            if (id.getBytes("gbk").length > 50) {
                return ResultStruct.error(String.format("字段【%s】超长，最大长度为：50", "id"), ResultVO.class, null);
            }
        }

        if (createDate == null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.MONTH, -1);
            createDate = calendar.getTime();
        }

        ProjectBaseAllModel projectBaseAllModel = projectService.selectProjectBaseById(id);
        if (projectBaseAllModel != null) {
            ProjectAndParaModel projectAndParaModel = new ProjectAndParaModel();
            projectAndParaModel.setProjName(projectBaseAllModel.getProjName());
            projectAndParaModel.setContSignDate(projectBaseAllModel.getContSignDate());
            projectAndParaModel.setProjDoDate(projectBaseAllModel.getProjDoDate());
            projectAndParaModel.setProjOnlineDate(projectBaseAllModel.getProjOnlineDate());
            projectAndParaModel.setProjOverDate(projectBaseAllModel.getProjOverDate());
            projectAndParaModel.setProjOverSign(projectBaseAllModel.getProjOverSign());
            projectAndParaModel.setRemark(projectBaseAllModel.getRemark());
            projectAndParaModel.setTotalType(projectBaseAllModel.getTotalType());

            ProjAvgInParam projAvgInParam = new ProjAvgInParam();
            projAvgInParam.setProCode(id);
            projAvgInParam.setCurrentDate(createDate);
            projAvgInParam.setTotalType(projectBaseAllModel.getTotalType());
            if (projectBaseAllModel.getTotalType().equals("季")) {
                final int season = LhClass.getSeason(createDate);
                projAvgInParam.setNumIndex(season);
            }
            BigDecimal bigDecimal = projAvgService.selectProAvgByProCode(projAvgInParam);
            if (bigDecimal != null) {
                projectAndParaModel.setTotalValue(bigDecimal);
            } else {
                projectAndParaModel.setTotalValue(BigDecimal.valueOf(0));
            }
            return ResultStruct.success(projectAndParaModel);
        } else
            return ResultStruct.success(null);
    }

    /**
     * 展示端方法：D4，方法ID：SE2021072113534726405D54676DD2C
     *
     * @return 得到前20个项目列表
     */
    @ApiOperation(value = "展示端方法：D4[得到前20个项目列表],方法ID：SE2021072113534726405D54676DD2C", notes = "/projectController/V1/selectProjectD4OrderBy")
    @PostMapping("/V1/selectProjectD4OrderBy")
    public ResultVO selectProjectD4OrderBy() {
        return ResultStruct.success(getProject20OrderBy());
    }

    private List<ProjectD4Model> getProject20OrderBy() {
        return projectService.selectProjectD4OrderBy();
    }

    private List<String> get20IdOrderBy() {
        final List<ProjectD4Model> projectD4Models = getProject20OrderBy();
        if (projectD4Models != null) {
            List<String> list = new ArrayList<>(projectD4Models.size());
            for (ProjectD4Model item :
                    projectD4Models) {
                list.add(item.getId());
            }
            projectD4Models.clear();
            return list;
        } else {
            return null;
        }
    }

    /**
     * 展示端方法：T2，甘特图，方法ID：SE202107231733535297FF7E76857F5
     *
     * @param beginDate 表vou_project,字段名projDoDate:实施开始日期
     * @return 项目列表
     */
    @ApiOperation(value = "展示端方法：T2，甘特图[项目列表],方法ID：SE202107231733535297FF7E76857F5", notes = "/projectController/V1/selectProjectGantuChart?projDoDate=projDoDate&projOverDate=projOverDate")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "beginDate", value = "开始日期", dataType = "Date", required = true)
    })
    @PostMapping("/V1/selectProjectGantuChart")
    public ResultVO selectProjectGantuChart(@RequestParam(value = "beginDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date beginDate) {
        ProjectGantuInParam projectGantuInParam = new ProjectGantuInParam();
        projectGantuInParam.setProjDoDate(beginDate);
        List<ProjectGanTuResultModel> projectGanTuResultModels = null;
        final List<ProjectGantuModel> projectGantuModels = projectService.selectProjectGantuChart(projectGantuInParam);
        if (!projectGantuModels.isEmpty()) {
            projectGanTuResultModels = new ArrayList<>(projectGantuModels.size());
            for (ProjectGantuModel projectGanTuModel :
                    projectGantuModels) {
                ProjectGanTuResultModel projectGanTuResultModel = new ProjectGanTuResultModel();
                projectGanTuResultModel.setId(projectGanTuModel.getId());
                projectGanTuResultModel.setLabel(projectGanTuModel.getProjName());
                projectGanTuResultModel.setStart(projectGanTuModel.getProjDoDate());
                final Date date = new Date();
                long betweenDays = LhClass.getBetweenDays(beginDate, date);
                projectGanTuResultModel.setDuration(betweenDays);
                projectGanTuResultModel.setEnd(date);
                projectGanTuResultModels.add(projectGanTuResultModel);
            }
            projectGantuModels.clear();
        }
        return ResultStruct.success(projectGanTuResultModels);
    }

    /**
     * 展示端方法：T4，方法ID：SE20210724150503586825AACAEA3A8
     *
     * @return 得到前20个项目列表
     */
    @ApiOperation(value = "展示端方法：T4[得到前20个项目列表],方法ID：SE20210724150503586825AACAEA3A8", notes = "/projectController/V1/selectProjectT4")
    @PostMapping("/V1/selectProjectT4")
    public ResultVO selectProjectT4() {
        final List<String> list = get20IdOrderBy();
        if (!list.isEmpty()) {
            return ResultStruct.success(projectService.selectProjectD5(list));
        } else {
            return ResultStruct.success(null);
        }
    }

    /**
     * 展示端方法：P5，方法ID：SE2021072914142579492DDD71EB5E7
     *
     * @param productId 表vou_project,字段名id:产品ID
     * @return 得到前20个项目列表
     */
    @ApiOperation(value = "展示端方法：P5[得到前20个项目列表],方法ID：SE2021072914142579492DDD71EB5E7", notes = "/projectController/V1/selectProjectP5?id=id")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "productId", value = "产品ID", dataType = "String", required = true, defaultValue = "A1")
    })
    @PostMapping("/V1/selectProjectP5")
    public ResultVO selectProjectP5(@RequestParam(value = "productId") String productId) {
        final List<String> list = projectAndProductService.selectProjectListByProductId(productId);
        if (!list.isEmpty())
            return ResultStruct.success(projectService.selectProjectP5(list));
        else
            return ResultStruct.success(null);
    }
}